from datetime import datetime
from sqlalchemy.orm import Session
from core.logger import log
from db.models.chat_message import AndroidAppMQMessage
from db.mysql.call_task_customers import CallTaskCustomers
from db.mysql.call_tasks import CallTasks
from db.mysql.dao.call_task import CallTaskDao, CallTaskCustomerDao
from db.mysql.dao.customers import CustomersDAO
from db.mysql.users import Users
from db.pydantic.request.call_task import CallTasksCreateRequest, CallTasksCreateResponse, CallTasksListRequest, \
    CallTasksListResponse, CallTaskCustomerRequest, CallTaskCustomerResponse, CallTaskCustomerUpdateRequest
from services.rabbitmq_service import RabbitMQProductor, RabbitMQConsumer, RabbitMQConsumerCallTask


class CallTaskService:
    """轮呼拨号任务服务"""
    def __init__(self):
        pass
    async def create_call_task(self, req:CallTasksCreateRequest, db:Session,current_user:Users):
        """
        创建通话任务
        :param req:
        :param db:
        :return:
        """
        try:
            call_dao = CallTaskDao(db)
            call_customer_dao = CallTaskCustomerDao(db)
            cust_dao = CustomersDAO(db)
            cust_ids = []
            if req.customer_ids:
                cust_ids = req.customer_ids
                total_count = len(req.customer_ids)
                call_task_data = {
                    "task_name": req.task_name,
                    "total_count": total_count,
                    "remaining_count": total_count,
                    "created_by": req.created_by,
                    "channel": req.channel,
                    "user_id": current_user.user_id
                }
                db_call_task = call_dao.create_call_task(call_task_data, auto_commit=False)
            elif req.random_count:
                customers_list = cust_dao.get_random_customers(user_id=current_user.user_id,count=req.random_count,in_call_task=0)
                if not customers_list:
                    log.info("没有可分配的客户")
                    return None
                total_count = req.random_count
                cust_ids = [customer.customer_id for customer in customers_list]
                call_task_data = {
                    "task_name": req.task_name,
                    "total_count": total_count,
                    "remaining_count": total_count,
                    "created_by": req.created_by,
                    "channel": req.channel,
                    "user_id": current_user.user_id
                }
                db_call_task = call_dao.create_call_task(call_task_data, auto_commit=False)
            else:
                log.info("参数传递错误，缺少customer_ids，random_count")
                return None
            if not db_call_task:
                return  None
            # 批量处理客户关联和状态更新
            call_customer_data_list = []
            for cust_id in cust_ids:
                # 创建任务关联的客户表，并且更新客户表中这些客户的in_call_task字段为1
                call_customer_data = {
                    "task_id": db_call_task.id,
                    "customer_id": cust_id
                }
                call_customer_data_list.append(call_customer_data)
                update_result = cust_dao.update_customer_by_customer_id(cust_id, {"in_call_task": 1,"current_task_id":db_call_task.id},auto_commit= False)
                if not update_result:
                    raise Exception(f"更新客户 {cust_id} in_call_task 失败！")
            # 批量插入
            if call_customer_data_list:
                call_customer_dao.bulk_insert_call_task_customers(call_customer_data_list, auto_commit=False)

            # 提交事务
            db.commit()
            response = CallTasksCreateResponse(task_id=db_call_task.id, total_count=total_count, message="创建成功")
            return response

        except Exception as e:
            # 回滚事务
            db.rollback()
            log.error(e)
            return None

    async def list_call_task(self, req: CallTasksListRequest, db: Session, current_user: Users):
        """
        列出通话任务服务
        """
        try:
            # 判断是否为超级管理员
            user_id = None if current_user.is_superuser else current_user.user_id
            call_dao = CallTaskDao(db)
            # 调用DAO获取任务列表
            tasks, total_count = call_dao.get_call_tasks(
                page=req.page,
                page_size=req.page_size,
                status=req.status,
                user_id=user_id,  # 超级管理员传None，普通用户传user_id
                created_by=req.created_by
            )
            tasks_list = [task.to_dict() for task in tasks]
            response = CallTasksListResponse(tasks=tasks_list, total=total_count)
            return response
        except Exception as e:
            log.error(f"列出轮呼任务失败: {str(e)}")
            return None


    async def list_call_task_customer(self,task_id:int,req:CallTaskCustomerRequest,db:Session):
        try:
            call_dao = CallTaskDao(db)
            #获取任务列表中的客户id
            if req.call_status:
                results, total_count = call_dao.get_call_task_customers_with_status(task_id,page=req.page, page_size=req.page_size,call_status=req.call_status)
            else:
                results, total_count = call_dao.get_call_task_customers_with_status(task_id,page=req.page, page_size=req.page_size)
            customers_list=[]
            for customers,call_status,call_result,call_time,connected_time,completed_time,call_duration in results:
                cust = customers.to_dict()
                cust["call_status"] = call_status
                cust["call_result"] = call_result
                cust["call_time"] = call_time
                cust["connected_time"] = connected_time
                cust["completed_time"] = completed_time
                cust["call_duration"] = call_duration
                customers_list.append(cust)
            log.info(f"列出轮呼任务客户成功，共{total_count}条数据")
            response = CallTaskCustomerResponse(customers=customers_list, total=total_count, task_info=call_dao.get_call_task_by_task_id(task_id).to_dict())
            return response
        except Exception as e:
            log.error(e)
            return None

    async def start_task(self,task_id:int,db:Session):
        """
        启动通话任务 将轮呼任务中的客户添加到消费者中
        :param task_id:
        :param db:
        :return:
        """
        try:
            call_dao = CallTaskDao(db)
            product = RabbitMQProductor()
            db_call_task = call_dao.get_call_task_by_task_id(task_id)
            if not db_call_task:
                raise Exception("任务不存在")
            customers,total_count = call_dao.get_all_call_task_customers(task_id)
            channel = db_call_task.channel
            msg = [AndroidAppMQMessage(phone=cust.phone, device_id=channel, name=cust.customer_name, description=cust.customer_situation,task_id=task_id,customer_id=cust.customer_id) for cust in  customers]
            await product.productor_message_batch(msg)
            call_task_data = {
                "status": "running",
                "started_at": datetime.now()
            }
            result = call_dao.update_call_task(task_id,call_task_data)
        except Exception as e:
            log.error(e)
            raise

    async def cancel_task(self,task_id:int,db:Session):
        """
        取消通话任务 将一些出问题的任务取消删除掉，如果mq中还有剩余任务，也将mq进行清空
        :param task_id:
        :param db:
        :return:
        """
        try:
            call_task_dao= CallTaskDao(db)
            customer_dao = CustomersDAO(db)
            # 1. 查询任务表是否有当前记录
            task: CallTasks = call_task_dao.get_call_task_by_task_id(task_id)
            if not task:
                raise Exception("任务不存在，请检查是否有当前任务")
            call_task_dao.update_call_task(task_id,{"status": "cancelled"})
            call_task_cust_dao = CallTaskCustomerDao(db)
            task_customers_list: list[CallTaskCustomers] = call_task_cust_dao.get_task_customers(task_id)
            # 更新客户是否在轮呼任务中的状态
            result = customer_dao.batch_update_call_task_customers([customer.customer_id for customer in task_customers_list],
                                                          auto_commit=False)
            channel = task.channel
            mq = RabbitMQConsumerCallTask(channel =channel)

            def filter_by_task_id(message_data):
                return message_data.get('task_id') == int(task_id)
            await mq.selective_clear_queue(filter_by_task_id)

            db.commit()
            return  result
        except Exception as e:
            log.error(e)
            db.rollback()
            raise

    async def stop_task(self,task_id:int,db:Session):
        """
        取消通话任务 将一些出问题的任务取消删除掉，如果mq中还有剩余任务，也将mq进行清空
        :param task_id:
        :param db:
        :return:
        """
        try:
            call_task_dao= CallTaskDao(db)
            customer_dao = CustomersDAO(db)
            # 1. 查询任务表是否有当前记录
            task: CallTasks = call_task_dao.get_call_task_by_task_id(task_id)
            if not task:
                raise Exception("任务不存在，请检查是否有当前任务")
            call_task_dao.update_call_task(task_id,{"status": "stopped"})
            call_task_cust_dao = CallTaskCustomerDao(db)
            task_customers_list: list[CallTaskCustomers] = call_task_cust_dao.get_task_customers(task_id)
            # 更新客户是否在轮呼任务中的状态
            result = customer_dao.batch_update_call_task_customers([customer.customer_id for customer in task_customers_list],
                                                          auto_commit=False)
            channel = task.channel
            mq = RabbitMQConsumerCallTask(channel =channel)

            def filter_by_task_id(message_data):
                return message_data.get('task_id') == int(task_id)
            await mq.selective_clear_queue(filter_by_task_id)

            db.commit()
            return  result
        except Exception as e:
            log.error(e)
            db.rollback()
            raise

    async def complete_task(self,task_id:int,db:Session):
        """
        完成通话任务 如果确实完成，就将完成客户放回公海
        :param task_id:
        :param db:
        :return:
        """
        try:
            # 1. 查询任务是否存在
            call_task_cust_dao = CallTaskCustomerDao(db)
            call_task_dao = CallTaskDao(db)
            customer_dao = CustomersDAO(db)
            task_customers_list : list[CallTaskCustomers] = call_task_cust_dao.get_task_customers(task_id)
            if not task_customers_list:
                raise Exception("任务客户不存在，请检查是否有当前任务")
            flag = False    # 任务是否完成 默认是完成的
            for task_customer in task_customers_list:
                if task_customer.call_status != "completed":
                    flag = True # 任务未完成
                    break
            # 4. 更新任务状态和完成时间
            if flag:
                return {"message": "任务未完成"}
            else:
                call_task_data = {
                    "status": "completed",
                    "completed_at": datetime.now()
                }
                # 更新任务表状态
                result = call_task_dao.update_call_task(task_id,call_task_data,auto_commit=False)
                # 更新客户是否在轮呼任务中的状态
                customer_dao.batch_update_call_task_customers([customer.customer_id for customer in task_customers_list],auto_commit= False)
                db.commit()
                return {"message": "任务完成"}
        except Exception as e:
            log.error(e)
            db.rollback()
            raise



    async def update_task_customer_status(self,task_id:int,customer_id:str,req:CallTaskCustomerUpdateRequest,db:Session):
        """
        更新任务客户状态
        :param task_id:
        :param customer_id:
        :param req:
        :param db:
        :return:
        """
        try:
            call_task_cust_dao = CallTaskCustomerDao(db)
            # 构建更新数据
            if req.call_result:
                call_task_cust_data = {
                    "call_status": req.call_status,
                    "call_result": req.call_result
                }
            else:
                call_task_cust_data = {
                    "call_status": req.call_status
                }
            if req.call_status == "connected":
                call_task_cust_data["connected_time"] = datetime.now().isoformat()
            elif req.call_status == "completed":
                call_task_cust_data["completed_time"] = datetime.now().isoformat()
            elif req.call_status == "dialing":
                call_task_cust_data["call_time"] = datetime.now().isoformat()
            call_task_cust_dao.update_task_customer(task_id,customer_id,call_task_cust_data)
            return {"message": "更新任务客户状态成功"}
        except Exception as e:
            log.error(e)
            raise

    async def reduce_task_number(self,task_id:int,db:Session):
        """
        任务数量减1
        :param task_id:
        :param db:
        :return:
        """
        try:
            call_task_dao = CallTaskDao(db)
            call_task_dao.reduce_task_number(task_id)
            return {"message": "任务数量减1成功"}
        except Exception as e:
            log.error(e)
            raise
def get_call_task_service():
    return CallTaskService()